home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / DELPHI / RGNAV.ZIP / RGNAV.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-05-25  |  29.9 KB  |  1,038 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {       Intelligent Base Navigator                      }
  4. {                                                       }
  5. {       Copyright (c) 1995, 1996 by Rohit Gupta         }
  6. {                                                       }
  7. {*******************************************************}
  8.  
  9. unit RgNav;
  10.  
  11. {$R-,S-,I-,O-,F-,A+,U+,K+,W-,V+,B-,X+,T-,P+,L+,Y+,D-}
  12.  
  13. interface
  14.  
  15. uses SysUtils, WinTypes, WinProcs, Messages, Classes, Controls, Graphics,
  16.   Menus, ExtCtrls, Buttons, RgUseful;
  17.  
  18. const
  19.   InitRepeatPause = 400;  { pause before repeat timer (ms) }
  20.   NormRepeatPause = 100;  { pause before hint window displays (ms)}
  21.   BtnSpaceSize    =  5;   { size of space between special buttons }
  22.  
  23.   SHntOfs         = 60000;
  24.   SCapOfs         = 60100;
  25.   SKeyOfs         = 60200;
  26.   SInsertQuestion = 60310;
  27.   SDeleteQuestion = 60311;
  28.   SEditQuestion   = 60312;
  29.   SPostQuestion   = 60317;
  30.   SCancelQuestion = 60318;
  31.  
  32. type
  33.   TNavButton = class;
  34.  
  35.   TNavGlyph   = (ngEnabled, ngDisabled);
  36.   TAllNavBtn  = (nbFirst,  nbPrior,  nbNext,  nbLast,   nbKey,
  37.                  nbSearch, nbTable,  nbForm,  nbPrint,  nbRefresh,
  38.                  nbInsert, nbDelete, nbEdit,  nbExtra1, nbExtra2,
  39.                  nbExtra3, nbHint,   nbPost,  nbCancel);
  40.   TNormNavBtn = nbFirst..nbExtra3;
  41.   TEditNavBtn = nbHint..nbCancel;
  42.   TNavColors  = (ncBlack, ncBlue, ncRed);
  43.   TBtnSize    = (X1,X2,X3,X4,X5);
  44.  
  45.   TAllBtnSet   = set of TAllNavBtn;
  46.   TNormBtnSet  = set of TNormNavBtn;
  47.   TNavBtnStyle = set of (nsAllowTimer, nsFocusRect);
  48.  
  49.   ENavClick = procedure (Sender: TObject; Button: TAllNavBtn) of object;
  50.  
  51. { TRGNavigator }
  52.  
  53.   TRGNavigatorX = class (TCustomPanel)
  54.   private
  55.     FVisibleButtons: TAllBtnSet;
  56.     VisibleCopy:     TAllBtnSet;
  57.     FVisibleHint   : Boolean;
  58.     FHints         : TStrings;
  59.     EditBtnWidth,
  60.     ButtonWidth    : SmallInt;
  61.     MinBtnSize     : TPoint;
  62.     FocusedButton  : TAllNavBtn;
  63.     FConfirmDelete,
  64.     FConfirmInsert,
  65.     FConfirmEdit,
  66.     FConfirmPost,
  67.     FConfirmCancel : Boolean;
  68.     FMenu: TMenuITem;
  69.  
  70.     FScrlColor,
  71.     FFuncColor,
  72.     FCtrlColor,
  73.     FToolColor     : TNavColors;
  74.  
  75.     FKeySize,
  76.     FEx1Size,
  77.     FEx2Size,
  78.     FEx3Size       : TBtnSize;
  79.  
  80.     procedure SetButtonColor (I : TAllNavBtn);
  81.     procedure SetScrlColor (Value : TNavColors);
  82.     procedure SetFuncColor (Value : TNavColors);
  83.     procedure SetCtrlColor (Value : TNavColors);
  84.     procedure SetToolColor (Value : TNavColors);
  85.  
  86.     procedure SetBtnSize   (var Target, Value : TBtnSize);
  87.     procedure SetKeySize   (Value : TBtnSize);
  88.     procedure SetEx1Size   (Value : TBtnSize);
  89.     procedure SetEx2Size   (Value : TBtnSize);
  90.     procedure SetEx3Size   (Value : TBtnSize);
  91.  
  92.     function  GetCapt1 : string;
  93.     function  GetCapt2 : string;
  94.     function  GetCapt3 : string;
  95.     procedure SetCaption (Idx : TAllNavBtn; Value : string);
  96.     procedure SetCapt1 (Value : string);
  97.     procedure SetCapt2 (Value : string);
  98.     procedure SetCapt3 (Value : string);
  99.  
  100.     procedure SetMenu (Value : TMenuItem);
  101.  
  102.     procedure InitButtons;
  103.     procedure InitHints;
  104.     procedure Click(Sender: TObject);
  105.     procedure BtnMouseDown (Sender: TObject; Button: TMouseButton;
  106.                             Shift: TShiftState; X, Y: Integer);
  107.     function  GetVisible : TNormBtnSet;
  108.     procedure SetVisible(Value: TNormBtnSet);
  109.     procedure SetMenuVisible(Btn : SmallInt; Value: Boolean);
  110.     procedure AdjustSize (var W, H : SmallInt);
  111.     procedure SetHints(Value: TStrings);
  112.     procedure WMSize(var Message: TWMSize);  message WM_SIZE;
  113.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  114.     procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  115.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  116.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  117.   protected
  118.     FOnNavClick: ENavClick;
  119.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  120. (*
  121.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  122. *)
  123.   public
  124.     Buttons: array[TAllNavBtn] of TNavButton;
  125.     Confirmed : boolean;
  126.     DLActive,
  127.     DLEditing,
  128.     DLCanModify,
  129.     DLBOF,
  130.     DLEOF  : Boolean;
  131.     constructor Create(AOwner: TComponent); override;
  132.     destructor Destroy; override;
  133.     procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  134.     procedure BtnClick(Index: TAllNavBtn; CallUserClick : Boolean); virtual;
  135.     procedure DataChanged;
  136.     procedure EditingChanged;
  137.     procedure ActiveChanged;
  138.     procedure Loaded; override;
  139.   published
  140.     property VisibleButtons: TNormBtnSet read GetVisible write SetVisible
  141.              default [nbFirst,  nbPrior,  nbNext,   nbLast,   nbKey,
  142.                       nbSearch, nbTable,  {nbForm,} nbPrint,  nbRefresh,
  143.                       nbInsert, nbDelete, nbEdit,   nbExtra1, nbExtra2, nbExtra3];
  144.     property VisibleHint : Boolean read FVisibleHint write FVisibleHint default True;
  145.     property Align;
  146.     property Ctl3D;
  147.     property DragCursor;
  148.     property DragMode;
  149.     property Enabled;
  150.     property Font;
  151.     property Hints: TStrings read FHints write SetHints;
  152.     property ParentCtl3D;
  153.     property ParentFont;
  154.     property ParentShowHint;
  155.     property PopupMenu;
  156.     property ConfirmDelete: Boolean read FConfirmDelete write FConfirmDelete default True;
  157.     property ConfirmInsert: Boolean read FConfirmInsert write FConfirmInsert default True;
  158.     property ConfirmEdit:   Boolean read FConfirmEdit   write FConfirmEdit   default True;
  159.     property ConfirmPost:   Boolean read FConfirmPost   write FConfirmPost   default True;
  160.     property ConfirmCancel: Boolean read FConfirmCancel write FConfirmCancel default True;
  161.     property ShowHint;
  162.     property TabOrder;
  163.     property TabStop;
  164.     property Visible;
  165.     property OnClick: ENavClick read FOnNavClick write FOnNavClick;
  166.     property OnDblClick;
  167.     property OnDragDrop;
  168.     property OnDragOver;
  169.     property OnEndDrag;
  170.     property OnEnter;
  171.     property OnExit;
  172.     property OnResize;
  173. {$IFDEF Win32}
  174.     property OnStartDrag;
  175. {$ENDIF Win32}
  176.     property ColorScroll:   TNavColors read FScrlColor write SetScrlColor;
  177.     property ColorFunc:     TNavColors read FFuncColor write SetFuncColor;
  178.     property ColorCtrl:     TNavColors read FCtrlColor write SetCtrlColor;
  179.     property ColorTool:     TNavColors read FToolColor write SetToolColor;
  180.     property SizeOfKey:     TBtnSize   read FKeySize   write SetKeySize default X3;
  181.     property SizeOfExtra1:  TBtnSize   read FEx1Size   write SetEx1Size default X3;
  182.     property SizeOfExtra2:  TBtnSize   read FEx2Size   write SetEx2Size default X3;
  183.     property SizeOfExtra3:  TBtnSize   read FEx3Size   write SetEx3Size default X3;
  184.     property Menu:          TMenuItem  read FMenu      write SetMenu;
  185.     property CaptionExtra1: string     read GetCapt1   write SetCapt1;
  186.     property CaptionExtra2: string     read GetCapt2   write SetCapt2;
  187.     property CaptionExtra3: string     read GetCapt3   write SetCapt3;
  188.   end;
  189.  
  190. { TNavButton }
  191.  
  192.   TNavButton = class(TSpeedButton)
  193.   private
  194.     FIndex: TAllNavBtn;
  195.     FNavStyle: TNavBtnStyle;
  196.     FRepeatTimer: TTimer;
  197.     procedure TimerExpired(Sender: TObject);
  198.   protected
  199.     procedure Paint; override;
  200.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  201.       X, Y: Integer); override;
  202.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  203.       X, Y: Integer); override;
  204.   public
  205.     destructor Destroy; override;
  206.     property NavStyle: TNavBtnStyle read FNavStyle write FNavStyle;
  207.     property Index : TAllNavBtn read FIndex write FIndex;
  208.   end;
  209.  
  210. const
  211.   BtnStateName : array[TNavGlyph] of PChar = ('EN', 'DI');
  212.  
  213.   BtnTypeName  : array[TAllNavBtn] of string[10]
  214.                = ('First', 'Prior',  'Next',   'Last',    'Key',    'Search',
  215.                   'Table', 'Form',   'Print',  'Refresh', 'Insert', 'Delete',
  216.                   'Edit',  'Extra1', 'Extra2', 'Extra3',  'Hint',   'Post',
  217.                   'Cancel');
  218.  
  219. procedure RegisterRGNavigatorX;
  220.  
  221. implementation
  222.  
  223. uses Dialogs;
  224.  
  225. {$IFDEF Win32}
  226. {$R RGNAV.R32}
  227. {$ELSE}
  228. {$R RGNAV.R16}
  229. {$ENDIF}
  230.  
  231.  
  232. { TRGNavigatorX }
  233.  
  234. constructor TRGNavigatorX.Create(AOwner: TComponent);
  235. begin
  236.   inherited Create(AOwner);
  237. (*
  238.   ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] + [csFramed, csOpaque];
  239. *)
  240.   ControlStyle := ControlStyle - [csAcceptsControls, csSetCaption] + [csOpaque];
  241.   if not NewStyleControls
  242.   then ControlStyle := ControlStyle + [csFramed];
  243.   FVisibleButtons := [nbFirst,  nbPrior,  nbNext,   nbLast,    nbKey,
  244.                       nbSearch, nbTable, {nbForm,}  nbPrint,  nbRefresh,
  245.                       nbInsert, nbDelete, nbEdit,   nbExtra1, nbExtra2,
  246.                       nbExtra3];
  247.   FKeySize := X4;
  248.   FEx1Size := X3;
  249.   FEx2Size := X3;
  250.   FEx3Size := X3;
  251.   FHints   := TStringList.Create;
  252.   InitButtons;
  253.   BevelOuter := bvNone;
  254.   BevelInner := bvNone;
  255.   Width      := 241;
  256.   Height     := 25;
  257.   ButtonWidth    := 0;
  258.   FocusedButton  := nbFirst;
  259.   FConfirmDelete := True;
  260.   FConfirmInsert := True;
  261.   FConfirmEdit   := True;
  262.   FConfirmPost   := True;
  263.   FConfirmCancel := True;
  264.   DLActive       := False;
  265.   DLEditing      := False;
  266.   DLCanModify    := False;
  267.   DLBOF          := False;
  268.   DLEOF          := False;
  269.   FVisibleHint   := True;
  270. end;
  271.  
  272. destructor TRGNavigatorX.Destroy;
  273. begin
  274.   FHints.Free;
  275.   inherited Destroy;
  276. end;
  277.  
  278. procedure TRGNavigatorX.SetButtonColor (I : TAllNavBtn);
  279.   procedure SetIt (Col : TNavColors);
  280.   begin
  281.     with Buttons[I]
  282.     do begin
  283.        ParentFont := True;
  284.        with Font
  285.        do case Col of
  286.             ncBlue : Color := clBlue;
  287.             ncRed  : Color := clRed;
  288.             else     Color := clBlack;
  289.        end;
  290.     end;
  291.   end;
  292.  
  293. var
  294.   Cl : char;
  295.   ResName: array[0..40] of Char;
  296. begin
  297.   case I of
  298.        nbFirst,nbPrior,
  299.        nbNext,nbLast,nbKey       : begin
  300.                                      Cl := char(ord(FScrlColor)+$30);
  301.                                      SetIt (FScrlColor);
  302.                                    end;
  303.        nbRefresh,nbSearch,
  304.        nbTable,nbForm,nbPrint    : begin
  305.                                      Cl := char(ord(FFuncColor)+$30);
  306.                                      SetIt (FFuncColor);
  307.                                    end;
  308.        nbInsert,nbDelete,
  309.        nbEdit,nbCancel,nbPost    : begin
  310.                                      Cl := char(ord(FCtrlColor)+$30);
  311.                                      SetIt (FCtrlColor);
  312.                                    end;
  313.        nbExtra1,nbExtra2,
  314.        nbExtra3,nbHint           : begin
  315.                                      Cl := char(ord(FToolColor)+$30);
  316.                                      SetIt (FToolColor);
  317.                                    end;
  318.        else                        Cl := '0';
  319.   end;
  320.   Buttons[I].Glyph.Handle := LoadBitmap(HInstance,
  321.                           StrFmt(ResName, '%srgn_%s', [Cl,BtnTypeName[I]]));
  322. end;
  323.  
  324. procedure TRGNavigatorX.SetScrlColor (Value : TNavColors);
  325. begin
  326.   if Value = FScrlColor
  327.   then exit;
  328.   FScrlColor := Value;
  329.   SetButtonColor (nbFirst);
  330.   SetButtonColor (nbPrior);
  331.   SetButtonColor (nbNext);
  332.   SetButtonColor (nbLast);
  333.   SetButtonColor (nbKey);
  334. end;
  335.  
  336. procedure TRGNavigatorX.SetFuncColor (Value : TNavColors);
  337. begin
  338.   if Value = FFuncColor
  339.   then exit;
  340.   FFuncColor := Value;
  341.   SetButtonColor (nbSearch);
  342.   SetButtonColor (nbTable);
  343.   SetButtonColor (nbForm);
  344.   SetButtonColor (nbPrint);
  345.   SetButtonColor (nbRefresh);
  346. end;
  347.  
  348. procedure TRGNavigatorX.SetCtrlColor (Value : TNavColors);
  349. begin
  350.   if Value = FCtrlColor
  351.   then exit;
  352.   FCtrlColor := Value;
  353.   SetButtonColor (nbInsert);
  354.   SetButtonColor (nbDelete);
  355.   SetButtonColor (nbEdit);
  356.   SetButtonColor (nbCancel);
  357.   SetButtonColor (nbPost);
  358. end;
  359.  
  360. procedure TRGNavigatorX.SetToolColor (Value : TNavColors);
  361. begin
  362.   if Value = FToolColor
  363.   then exit;
  364.   FToolColor := Value;
  365.   SetButtonColor (nbExtra1);
  366.   SetButtonColor (nbExtra2);
  367.   SetButtonColor (nbExtra3);
  368.   SetButtonColor (nbHint);
  369. end;
  370.  
  371. procedure TRGNavigatorX.SetBtnSize (var Target, Value : TBtnSize);
  372. var
  373.   W, H : SmallInt;
  374. begin
  375.   if Value = Target
  376.   then exit;
  377.   Target := Value;
  378.   W := Width;
  379.   H := Height;
  380.   AdjustSize (W,H);
  381. end;
  382.  
  383. procedure TRGNavigatorX.SetKeySize (Value : TBtnSize);
  384. begin SetBtnSize (FKeySize,Value); end;
  385.  
  386. procedure TRGNavigatorX.SetEx1Size (Value : TBtnSize);
  387. begin SetBtnSize (FEx1Size,Value); end;
  388.  
  389. procedure TRGNavigatorX.SetEx2Size (Value : TBtnSize);
  390. begin SetBtnSize (FEx2Size,Value); end;
  391.  
  392. procedure TRGNavigatorX.SetEx3Size (Value : TBtnSize);
  393. begin SetBtnSize (FEx3Size,Value); end;
  394.  
  395. function TRGNavigatorX.GetCapt1 : string;
  396. begin GetCapt1 := Buttons [nbExtra1].Caption; end;
  397.  
  398. function TRGNavigatorX.GetCapt2 : string;
  399. begin GetCapt2 := Buttons [nbExtra2].Caption; end;
  400.  
  401. function TRGNavigatorX.GetCapt3 : string;
  402. begin GetCapt3 := Buttons [nbExtra3].Caption; end;
  403.  
  404. procedure TRGNavigatorX.SetCaption (Idx : TAllNavBtn; Value : string);
  405. var
  406.   I : SmallInt;
  407. begin
  408.   if Buttons [Idx].Caption = Value
  409.   then Exit;
  410.   Buttons [Idx].Caption := Value;
  411.   if FMenu = nil
  412.   then exit;
  413.   with FMenu
  414.   do for I := 0 to Count-1
  415.      do if Items [I].Tag = ord(Idx)
  416.         then begin
  417.              Items [I].Caption := Value;
  418.              exit;
  419.         end;
  420. end;
  421.  
  422. procedure TRGNavigatorX.SetCapt1 (Value : string);
  423. begin SetCaption (nbExtra1,Value); end;
  424.  
  425. procedure TRGNavigatorX.SetCapt2 (Value : string);
  426. begin SetCaption (nbExtra2,Value); end;
  427.  
  428. procedure TRGNavigatorX.SetCapt3 (Value : string);
  429. begin SetCaption (nbExtra3,Value); end;
  430.  
  431. procedure TRGNavigatorX.SetMenu (Value : TMenuItem);
  432.   procedure InsertIt (const Nam, Cap, Key, Hnt : string; Tg : SmallInt);
  433.   var
  434.     Item : TMenuItem;
  435.   begin
  436.     Item := TMenuITem.Create (FMenu.Owner);
  437.     if not Assigned (Item)
  438.     then exit;
  439.     with Item
  440.     do begin
  441.        Name     := Nam+'Menu';
  442.        Caption  := Cap;
  443.        ShortCut := TextToShortCut(Key);
  444.        Hint     := Hnt;
  445.        OnClick  := Self.Click;
  446.        Tag      := Tg;
  447.     end;
  448.     FMenu.Add (Item);
  449.   end;
  450.  
  451.   procedure SetOnClick;  { Delphi loses above Onclick }
  452.   var
  453.     I : SmallInt;
  454.   begin
  455.     with FMenu
  456.     do for I := 0 to Count-1
  457.        do with Items [I]
  458.           do if Caption <> '-'
  459.              then OnClick := Self.Click;
  460.   end;
  461.  
  462. var
  463.   I      : TAllNavBtn;
  464.   J      : SmallInt;
  465.   S1, S2 : String;
  466. begin
  467.   if Value = FMenu
  468.   then exit;
  469.   FMenu := Value;
  470.   if not assigned (FMenu)
  471.   then exit;
  472.  
  473.   if not (csDesigning in ComponentState)
  474.   then begin
  475.        SetOnClick;
  476.        Exit;
  477.   end;
  478.  
  479.   with FMenu      { If FirstMenu or Insert exist, then abort }
  480.   do if Count > 0
  481.   then begin
  482.        S1 := BtnTypeName [nbFirst] + 'Menu';
  483.        S2 := BtnTypeName [nbInsert] + 'Menu';
  484.        for J := 0 to Count-1
  485.        do with Items [J]
  486.           do if (Name = S1) or (Name = S2)
  487.              then exit;
  488.   end;
  489.  
  490.   for I := Low(TAllNavBtn) to High(TAllNavBtn)
  491.   do if Buttons [I].Enabled
  492.      and (I <> nbHint)
  493.      then begin
  494.           case I of
  495.                nbSearch,
  496.                nbInsert,
  497.                nbExtra1,
  498.                nbPost : InsertIt (BtnTypeName[I]+'_','-','','',0);
  499.           end;
  500.           case I of
  501.                nbExtra1,
  502.                nbExtra2,
  503.                nbExtra3 : S1 := Buttons [I].Caption;
  504.                else       S1 := LoadStr (SCapOfs+ord(I));
  505.  
  506.           end;
  507.           InsertIt (BtnTypeName[I],S1,LoadStr (SKeyOfs+ord(I)),Buttons[I].Hint,ord(I));
  508.      end;
  509. end;
  510.  
  511. procedure TRGNavigatorX.InitButtons;
  512. var
  513.   I: TAllNavBtn;
  514.   Btn: TNavButton;
  515.   X: SmallInt;
  516. begin
  517.   MinBtnSize := Point(20, 18);
  518.   X := 0;
  519.   for I := Low(Buttons) to High(Buttons)
  520.   do begin
  521.     Btn := TNavButton.Create (Self);
  522.     Btn.Index := I;
  523.     Btn.Visible := I in FVisibleButtons;
  524.     Btn.Enabled := True;
  525.     Btn.SetBounds (X, 0, MinBtnSize.X, MinBtnSize.Y);
  526.     Btn.NumGlyphs := 2;
  527.     Btn.OnClick := Click;
  528.     Btn.OnMouseDown := BtnMouseDown;
  529.     Btn.Parent := Self;
  530.     Buttons[I] := Btn;
  531.     SetButtonColor (I);
  532.     X := X + MinBtnSize.X;
  533.     case I of
  534.          nbHint   : Buttons [I].Margin := 0;
  535.          nbKey,
  536.          nbExtra1,
  537.          nbExtra2,
  538.          nbExtra3 : begin
  539.                       if I = nbKey
  540.                       then Buttons[I].Caption := 'Primary'
  541.                       else Buttons[I].Caption := BtnTypeName [I];
  542.                       Buttons[I].Margin  := 3;
  543.                     end;
  544.     end;
  545.   end;
  546.   InitHints;
  547.   Buttons[nbPrior].NavStyle := Buttons[nbPrior].NavStyle + [nsAllowTimer];
  548.   Buttons[nbNext]. NavStyle := Buttons[nbNext]. NavStyle + [nsAllowTimer];
  549. end;
  550.  
  551. procedure TRGNavigatorX.InitHints;
  552. var
  553.   I: SmallInt;
  554.   J: TAllNavBtn;
  555. begin
  556.   for J := Low(Buttons) to High(Buttons)
  557.   do Buttons[J].Hint := LoadStr (SHntOfs+ord(J));
  558.   J := Low(Buttons);
  559.   for I := 0 to (FHints.Count - 1)
  560.   do begin
  561.     if FHints.Strings[I] <> ''
  562.     then Buttons[J].Hint := FHints.Strings[I];
  563.     if J = High(Buttons)
  564.     then Exit;
  565.     Inc(J);
  566.   end;
  567. end;
  568.  
  569. procedure TRGNavigatorX.SetHints(Value: TStrings);
  570. begin
  571.   FHints.Assign(Value);
  572.   InitHints;
  573. end;
  574.  
  575. function TRGNavigatorX.GetVisible : TNormBtnSet;
  576. begin
  577.   Result := FVisibleButtons * [low(TNormNavBtn)..high(TNormNavBtn)];
  578. end;
  579.  
  580. procedure TRGNavigatorX.SetVisible(Value: TNormBtnSet);
  581. var
  582.   I: TAllNavBtn;
  583.   W, H: SmallInt;
  584. begin
  585.   W := Width;
  586.   H := Height;
  587.   if (nbTable in FVisibleButtons) and (nbForm in Value)
  588.   then Value := Value - [nbTable];
  589.   if (nbForm in FVisibleButtons) and (nbTable in Value)
  590.   then Value := Value - [nbForm];
  591.   FVisibleButtons := Value;
  592.   for I := Low(Buttons) to High(Buttons)
  593.   do begin
  594.      Buttons[I].Visible := I in FVisibleButtons;
  595.      if assigned (FMenu)
  596.      then SetMenuVisible (ord(I),Buttons[I].Visible);
  597.   end;
  598.   AdjustSize (W, H);
  599.   if (W <> Width) or (H <> Height)
  600.   then inherited SetBounds (Left, Top, W, H);
  601.   Invalidate;
  602. end;
  603.  
  604. procedure TRGNavigatorX.SetMenuVisible(Btn : SmallInt; Value: Boolean);
  605. var
  606.   I: SmallInt;
  607. begin
  608.   if assigned (FMenu)
  609.   then with FMenu
  610.        do for I := 1 to Count-1
  611.           do if Items [I].Tag = Btn
  612.              then Items [I].Enabled := Value;
  613. end;
  614.  
  615. procedure TRGNavigatorX.AdjustSize (var W, H: SmallInt);
  616. var
  617.   HintSize : SmallInt;
  618.   function GetButtonSIze (I : TAllNavBtn) : SmallInt;
  619.   begin
  620.       case I of
  621.            nbKey    : Result := ord(FKeySize);
  622.            nbExtra1 : Result := ord(FEx1Size);
  623.            nbExtra2 : Result := ord(FEx2Size);
  624.            nbExtra3 : Result := ord(FEx3Size);
  625.            nbHint   : if DLEditing
  626.                       then begin
  627.                            if HintSize <> 0
  628.                            then Result := HintSize
  629.                            else begin
  630.                                 Result := ((W-EditBtnWidth*2) div EditBtnWidth)-2;
  631.                                 if Result < 10       { Goes negative sometimes }
  632.                                 then Result := 10;
  633.                                 HintSize := Result;  { For Later }
  634.                            end;
  635.                       end
  636.                       else Result := 20;
  637.            else       Result := 0;
  638.       end;
  639.       Inc (Result);
  640.   end;
  641.  
  642. var
  643.   Count: SmallInt;
  644.   MinW: SmallInt;
  645.   I: TAllNavBtn;
  646.   LastBtn: TAllNavBtn;
  647.   BWidth,
  648.   Space, Temp, Remain,
  649.   X, VisibleBtns,
  650.   Extra : SmallInt;
  651.  
  652. begin
  653.   if (csLoading in ComponentState)
  654.   then Exit;
  655.   if Buttons[nbFirst] = nil
  656.   then Exit;
  657.  
  658.   HintSize := 0;
  659.   Count := 0;
  660.   VisibleBtns := 0;
  661.   LastBtn := High(Buttons);
  662.   for I := Low(Buttons) to High(Buttons)
  663.   do begin
  664.     if Buttons[I].Visible then
  665.     begin
  666.       Inc (Count,GetButtonSize(I));
  667.       Inc (VisibleBtns);
  668.       LastBtn := I;
  669.     end;
  670.   end;
  671.   if Count = 0 then Inc(Count);
  672.  
  673.   MinW := Count * (MinBtnSize.X - 1){ + 1};
  674.   if W < MinW
  675.   then W := MinW;
  676.   if H < MinBtnSize.Y
  677.   then H := MinBtnSize.Y;
  678.  
  679.   ButtonWidth := ((W - 1) div Count);
  680.   Temp := (Count * ButtonWidth){ + 1};   { Space Required }
  681.   Extra := 0;
  682.   while W-Temp > VisibleBtns           { If more than # butons }
  683.   do begin                             { Then distribute it }
  684.      Inc (Extra);
  685.      Inc (Temp,VisibleBtns);
  686.   end;
  687. (*
  688.   if Align = alNone   { Align if Required }  not really needed
  689.   then W := Temp;
  690. *)
  691.   X := 0;
  692.   Remain := W - Temp;
  693.   Temp := Count div 2;
  694.   for I := Low(Buttons) to High(Buttons)
  695.   do begin
  696.     if Buttons[I].Visible
  697.     then begin
  698.          Space := 0;
  699.          if Remain <> 0
  700.          then begin
  701.               Dec (Remain);
  702.               Space := 1;
  703.          end;
  704.          BWidth := ButtonWidth * GetButtonSize (I) + Extra;
  705.          Buttons[I].SetBounds (X, 0, BWidth + Space, Height);
  706.          Inc (X, BWidth + Space);
  707.          LastBtn := I;
  708.     end
  709.     else Buttons[I].SetBounds (Width + 1, 0, ButtonWidth, Height);
  710.   end;
  711.   if not DLEditing
  712.   then EditBtnWidth := ButtonWidth;
  713. end;
  714.  
  715. procedure TRGNavigatorX.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  716. var
  717.   W, H: SmallInt;
  718. begin
  719.   W := AWidth;
  720.   H := AHeight;
  721.   AdjustSize (W, H);
  722.   inherited SetBounds (ALeft, ATop, W, H);
  723. end;
  724.  
  725. procedure TRGNavigatorX.WMSize(var Message: TWMSize);
  726. var
  727.   W, H: SmallInt;
  728. begin
  729.   inherited;
  730.  
  731.   { check for minimum size }
  732.   W := Width;
  733.   H := Height;
  734.   AdjustSize (W, H);
  735.   if (W <> Width) or (H <> Height)
  736.   then inherited SetBounds(Left, Top, W, H);
  737.   Message.Result := 0;
  738. end;
  739.  
  740. procedure TRGNavigatorX.Click(Sender: TObject);
  741. begin
  742.   if Sender is TNavButton
  743.   then BtnClick (TNavButton (Sender).Index,TRUE)
  744.   else BtnClick (TAllNavBtn(TMenuItem(Sender).Tag),TRUE);
  745. end;
  746.  
  747. procedure TRGNavigatorX.BtnMouseDown(Sender: TObject; Button: TMouseButton;
  748.   Shift: TShiftState; X, Y: Integer);
  749. var
  750.   OldFocus: TAllNavBtn;
  751. begin
  752.   OldFocus := FocusedButton;
  753.   FocusedButton := TNavButton (Sender).Index;
  754.   if TabStop and (GetFocus <> Handle) and CanFocus
  755.   then begin
  756.     SetFocus;
  757.     if (GetFocus <> Handle)
  758.     then Exit;
  759.   end
  760.   else if TabStop and (GetFocus = Handle) and (OldFocus <> FocusedButton)
  761.   then begin
  762.     Buttons[OldFocus].Invalidate;
  763.     Buttons[FocusedButton].Invalidate;
  764.   end;
  765. end;
  766.  
  767. procedure TRGNavigatorX.BtnClick(Index: TAllNavBtn; CallUserClick : Boolean);
  768. begin
  769.   Confirmed := False;
  770.   case Index of
  771.         nbInsert : if not FConfirmInsert or
  772.                      (MessageDlg (LoadStr(SInsertQuestion),
  773.                       mtConfirmation, mbOKCancel, 0) <> idCancel)
  774.                    then Confirmed := True;
  775.         nbDelete : if not FConfirmDelete or
  776.                      (MessageDlg (LoadStr(SDeleteQuestion),
  777.                       mtConfirmation, mbOKCancel, 0) <> idCancel)
  778.                    then Confirmed := True;
  779.         nbEdit   : if not FConfirmEdit or
  780.                      (MessageDlg (LoadStr(SEditQuestion),
  781.                       mtConfirmation, mbOKCancel, 0) <> idCancel)
  782.                    then Confirmed := True;
  783.         nbCancel : if not FConfirmCancel or
  784.                      (MessageDlg (LoadStr(SCancelQuestion),
  785.                       mtConfirmation, [mbYes,mbNo], 0) = idYes)
  786.                    then Confirmed := True;
  787.         nbPost   : if not FConfirmPost or
  788.                      (MessageDlg (LoadStr(SPostQuestion),
  789.                       mtConfirmation, mbOKCancel, 0) <> idCancel)
  790.                    then Confirmed := True;
  791.   end;
  792.  
  793.   if CallUserClick
  794.   then begin
  795.        if (not (csDesigning in ComponentState))
  796.        then begin
  797.             if Confirmed
  798.             then case Index of
  799.                       nbInsert, nbEdit : begin
  800.                                               DLEditing   := True;
  801.                                               DLCanModify := True;
  802.                                               EditingChanged;
  803.                                          end;
  804.                       nbCancel, nbPost : begin
  805.                                               DLEditing   := False;
  806.                                               DLCanModify := True;
  807.                                               EditingChanged;
  808.                                               DataChanged;
  809.                                          end;
  810.                       nbDelete         : begin
  811.                                               DataChanged;
  812.                                          end;
  813.                  end;
  814.             if Assigned(FOnNavClick)
  815.             then FOnNavClick(Self, Index);
  816.        end;
  817.   end;
  818. end;
  819.  
  820. procedure TRGNavigatorX.WMSetFocus(var Message: TWMSetFocus);
  821. begin
  822.   Buttons[FocusedButton].Invalidate;
  823. end;
  824.  
  825. procedure TRGNavigatorX.WMKillFocus(var Message: TWMKillFocus);
  826. begin
  827.   Buttons[FocusedButton].Invalidate;
  828. end;
  829.  
  830. procedure TRGNavigatorX.KeyDown(var Key: Word; Shift: TShiftState);
  831. var
  832.   NewFocus: TAllNavBtn;
  833.   OldFocus: TAllNavBtn;
  834. begin
  835.   OldFocus := FocusedButton;
  836.   case Key of
  837.     VK_RIGHT:
  838.       begin
  839.         NewFocus := FocusedButton;
  840.         repeat
  841.           if NewFocus < High(Buttons)
  842.           then NewFocus := Succ(NewFocus);
  843.         until (NewFocus = High(Buttons)) or (Buttons[NewFocus].Visible);
  844.         if NewFocus <> FocusedButton
  845.         then begin
  846.           FocusedButton := NewFocus;
  847.           Buttons[OldFocus].Invalidate;
  848.           Buttons[FocusedButton].Invalidate;
  849.         end;
  850.       end;
  851.     VK_LEFT:
  852.       begin
  853.         NewFocus := FocusedButton;
  854.         repeat
  855.           if NewFocus > Low(Buttons)
  856.           then NewFocus := Pred(NewFocus);
  857.         until (NewFocus = Low(Buttons)) or (Buttons[NewFocus].Visible);
  858.         if NewFocus <> FocusedButton
  859.         then begin
  860.           FocusedButton := NewFocus;
  861.           Buttons[OldFocus].Invalidate;
  862.           Buttons[FocusedButton].Invalidate;
  863.         end;
  864.       end;
  865.     VK_SPACE:
  866.       begin
  867.         if Buttons[FocusedButton].Enabled
  868.         then Buttons[FocusedButton].Click;
  869.       end;
  870.   end;
  871. end;
  872.  
  873. procedure TRGNavigatorX.WMGetDlgCode(var Message: TWMGetDlgCode);
  874. begin
  875.   Message.Result := DLGC_WANTARROWS;
  876. end;
  877.  
  878. procedure TRGNavigatorX.DataChanged;
  879. var
  880. test,
  881.   UpEnable, DnEnable: Boolean;
  882. begin
  883.   UpEnable := Enabled and DLActive and not DLBOF;
  884.   DnEnable := Enabled and DLActive and not DLEOF;
  885.   Buttons[nbFirst].Enabled := UpEnable;
  886.   Buttons[nbPrior].Enabled := UpEnable;
  887.   Buttons[nbNext].Enabled := DnEnable;
  888.   Buttons[nbLast].Enabled := DnEnable;
  889.   Buttons[nbDelete].Enabled := Enabled and DLActive and DLCanModify and not (DLBOF and DLEOF);
  890. end;
  891.  
  892. procedure TRGNavigatorX.EditingChanged;
  893. var
  894.   CanModify: Boolean;
  895.   I        : TAllNavBtn;
  896.   W, H     : SmallInt;
  897. begin
  898.   CanModify := Enabled and DLActive and DLCanModify;
  899.   if CanModify
  900.   then if DLEditing
  901.        then begin
  902.             VisibleCopy := FVisibleButtons;
  903.             FVisibleButtons := [LOW(TEditNavBtn)..HIGH(TEditNavBtn)];
  904.             if not FVisibleHint
  905.             then Exclude (FVisibleButtons,nbHint);
  906.             W := Width;
  907.             H := Height;
  908.             for I := LOW(TNormNavBtn) to HIGH(TNormNavBtn)
  909.             do begin
  910.                Buttons[I].Visible := false;
  911.                if assigned (FMenu)
  912.                then SetMenuVisible (ord(I), False);
  913.             end;
  914.             for I := LOW(TEditNavBtn) to HIGH(TEditNavBtn)
  915.             do begin
  916.                if (I <> nbHint) or (FVisibleHint)
  917.                then Buttons[I].Visible := true;
  918.                if assigned (FMenu)
  919.                then SetMenuVisible (ord(I), True);
  920.             end;
  921.             AdjustSize (W, H);
  922.             if (W <> Width) or (H <> Height)
  923.             then inherited SetBounds (Left, Top, W, H);
  924.             Invalidate;
  925.        end
  926.        else begin
  927.             SetVisible (VisibleCopy);
  928.        end;
  929. end;
  930.  
  931. procedure TRGNavigatorX.ActiveChanged;
  932. var
  933.   I: TAllNavBtn;
  934. begin
  935. (*
  936.   if not (Enabled and DLActive)
  937.   then for I := Low(Buttons) to High(Buttons)
  938.        do Buttons[I].Enabled := False
  939.   else begin
  940.     DataChanged;
  941.     EditingChanged;
  942.   end;
  943. *)
  944. end;
  945.  
  946. procedure TRGNavigatorX.CMEnabledChanged(var Message: TMessage);
  947. begin
  948.   inherited;
  949.   if not (csLoading in ComponentState)
  950.   then ActiveChanged;
  951. end;
  952.  
  953. procedure TRGNavigatorX.Loaded;
  954. var
  955.   W, H: SmallInt;
  956. begin
  957.   inherited Loaded;
  958.   W := Width;
  959.   H := Height;
  960.   AdjustSize (W, H);
  961.   if (W <> Width) or (H <> Height)
  962.   then inherited SetBounds (Left, Top, W, H);
  963.   InitHints;
  964.   if not (csLoading in ComponentState)
  965.   then ActiveChanged;
  966. end;
  967.  
  968. {TNavButton}
  969.  
  970. destructor TNavButton.Destroy;
  971. begin
  972.   if FRepeatTimer <> nil
  973.   then FRepeatTimer.Free;
  974.   inherited Destroy;
  975. end;
  976.  
  977. procedure TNavButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
  978.   X, Y: Integer);
  979. begin
  980.   inherited MouseDown (Button, Shift, X, Y);
  981.   if nsAllowTimer in FNavStyle
  982.   then begin
  983.     if FRepeatTimer = nil
  984.     then FRepeatTimer := TTimer.Create(Self);
  985.  
  986.     FRepeatTimer.OnTimer := TimerExpired;
  987.     FRepeatTimer.Interval := InitRepeatPause;
  988.     FRepeatTimer.Enabled  := True;
  989.   end;
  990. end;
  991.  
  992. procedure TNavButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
  993.                                   X, Y: Integer);
  994. begin
  995.   inherited MouseUp (Button, Shift, X, Y);
  996.   if FRepeatTimer <> nil
  997.   then FRepeatTimer.Enabled  := False;
  998. end;
  999.  
  1000. procedure TNavButton.TimerExpired(Sender: TObject);
  1001. begin
  1002.   FRepeatTimer.Interval := NormRepeatPause;
  1003.   if (FState = bsDown) and MouseCapture
  1004.   then begin
  1005.     try
  1006.       Click;
  1007.     except
  1008.       FRepeatTimer.Enabled := False;
  1009.       raise;
  1010.     end;
  1011.   end;
  1012. end;
  1013.  
  1014. procedure TNavButton.Paint;
  1015. var
  1016.   R: TRect;
  1017. begin
  1018.   inherited Paint;
  1019.   if (GetFocus = Parent.Handle) and
  1020.      (FIndex = TRGNavigatorX (Parent).FocusedButton)
  1021.   then begin
  1022.     R := Bounds(0, 0, Width, Height);
  1023.     InflateRect(R, -3, -3);
  1024.     if FState = bsDown
  1025.     then OffsetRect(R, 1, 1);
  1026.     DrawFocusRect(Canvas.Handle, R);
  1027.   end;
  1028. end;
  1029.  
  1030. { Register }
  1031.  
  1032. procedure RegisterRGNavigatorX;
  1033. begin
  1034.   RegisterComponents('RG', [TRGNavigatorX]);
  1035. end;
  1036.  
  1037. end.
  1038.